package com.basic.backend.manager;

import cn.hutool.core.io.FileUtil;
import com.basic.backend.common.ErrorCode;
import com.basic.backend.config.CosClientConfig;
import com.basic.backend.exception.BusinessException;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.model.*;
import com.qcloud.cos.model.ciModel.persistence.PicOperations;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.*;
import java.util.logging.Logger;

import static com.qcloud.cos.demo.BucketRefererDemo.bucketName;
import static java.lang.System.*;

@Component
@Slf4j
public class CosManager {
    @Resource
    private CosClientConfig cosClientConfig;

    @Resource
    private COSClient cosClient;

    private static final Set<String> ALLOWED_IMAGE_TYPES = new HashSet<>(Arrays.asList(
            "jpg", "jpeg", "png", "gif", "bmp", "webp"
    ));

    public String getBucketName() {
        return cosClientConfig.getBucket();
    }

    public String getRegion() {
        return cosClientConfig.getRegion();
    }

    /**
     * 基础文件上传
     */
    public PutObjectResult putObject(String key, File file) {
        PutObjectRequest putObjectRequest = new PutObjectRequest(
                cosClientConfig.getBucket(),
                key,
                file
        );
        return cosClient.putObject(putObjectRequest);
    }

    /**
     * 删除文件
     */
    public void deleteObject(String key) {
        try {
            DeleteObjectRequest request = new DeleteObjectRequest(cosClientConfig.getBucket(), key);
            cosClient.deleteObject(request);
            log.debug("COS删除成功: {}", key);
        } catch (CosClientException e) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,
                    "文件删除失败: " + e.getMessage());
        }
    }

    /**
     * 生成预签名URL
     */
    public String generateUrl(String fileKey) {
        // 计算一年后的过期时间
        Date expirationDate = new Date(currentTimeMillis() + 1000L * 60 * 60 * 24 * 365);
        return cosClient.generatePresignedUrl(
                cosClientConfig.getBucket(),
                fileKey,
                expirationDate
        ).toString();
    }

    public void putObject(String fileKey, byte[] data) {
        // 参数校验
        if (fileKey == null || fileKey.isEmpty()) {
            throw new IllegalArgumentException("文件路径不能为空");
        }
        if (data == null || data.length == 0) {
            throw new IllegalArgumentException("文件内容不能为空");
        }
        if (data.length > 10 * 1024 * 1024) { // 10MB限制
            throw new IllegalArgumentException("文件大小超过10MB限制");
        }

        // 验证文件类型
        String fileExtension = FilenameUtils.getExtension(fileKey).toLowerCase();
        if (!ALLOWED_IMAGE_TYPES.contains(fileExtension)) {
            throw new IllegalArgumentException("禁止上传的文件类型: " + fileExtension);
        }

        // 配置元数据
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentLength(data.length);
        metadata.setContentType(getContentType(fileExtension));

        // 创建上传请求
        PutObjectRequest request = new PutObjectRequest(
                bucketName,
                fileKey,
                new ByteArrayInputStream(data),
                metadata
        );

        // 带重试机制的上传
        final int maxRetries = 3;
        for (int retry = 1; retry <= maxRetries; retry++) {
            try {
                cosClient.putObject(request);
                log.info("文件上传成功: {}", fileKey);
                return;
            } catch (CosClientException e) {
                if (retry == maxRetries) {
                    log.error("文件上传失败（已达最大重试次数）: {}", fileKey, e);
                    throw new RuntimeException("COS上传失败: " + e.getMessage(), e);
                }
                log.warn("上传失败开始重试({}/{}): {}", retry, maxRetries, fileKey);
                try {
                    Thread.sleep(1000 * retry); // 指数退避
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    // 根据扩展名获取Content-Type
    private String getContentType(String fileExtension) {
        switch (fileExtension) {
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "gif":
                return "image/gif";
            case "bmp":
                return "image/bmp";
            case "webp":
                return "image/webp";
            default:
                return "application/octet-stream";
        }
    }

}
